package com.atguigu.interview.study.juc;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author gcq
 * @Create 2020-12-07
 * 可重入锁：可重复可递归的调用的锁，在外层使用的锁，在内层任然可用，并且不发生死锁，这样的锁就是可重入锁
 *
 * 在一个synchronized修饰的方法或代码块内部
 * 调用本类的其他的synchronized修饰的方法或代码块时，是永远可以得到锁的
 */
public class  ReEnterLockDemo {

    static Object objectLockA = new Object();
    static Lock lock = new ReentrantLock();




    /**
     * 同步代码块
     */
    private static void synchronizedmethod1() {
        new Thread(() ->{
            synchronized (objectLockA) {
                System.out.println(Thread.currentThread().getName() + "\t" + "-------外层调用");
                synchronized (objectLockA) {
                    System.out.println(Thread.currentThread().getName() + "\t" + "-------中层调用");
                    synchronized (objectLockA) {
                        System.out.println(Thread.currentThread().getName() + "\t" + "-------内层调用");
                    }
                }
            }
        },"t1").start();
    }

    public static void main(String[] args) {
        reentrantLockDemo();
    }

    private static void reentrantLockDemo() {
        /**
         * lock和unlock必须要相对应 加锁几次就需要减锁几次
         */
        new Thread(() -> {
            lock.lock();
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName()+ "\t 外层");
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName()+ "\t 内层");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
                lock.unlock();
            }
        },"t1").start();


        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("外外层");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        },"input thread name").start();
    }


        /**
         * 同步方法
         */
        public static void m1() {
            System.out.println(Thread.currentThread().getName() +"\t" +"外层");
            m2();
        }
        public static void m2() {
            System.out.println(Thread.currentThread().getName() +"\t" +"中层");
            m3();
        }
        public static void m3() {
            System.out.println(Thread.currentThread().getName() +"\t" +"内层");
        }

}